Skip to content

fix(native): expand a transition held in a variable - #497

Open
YevheniiKotyrlo wants to merge 2 commits into
nativewind:mainfrom
YevheniiKotyrlo:fix/transition-variable
Open

YevheniiKotyrlo wants to merge 2 commits into
nativewind:mainfrom
YevheniiKotyrlo:fix/transition-variable

Conversation

@YevheniiKotyrlo

@YevheniiKotyrlo YevheniiKotyrlo commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Problem

A transition held in a variable never reaches React Native as a transition:

  • transition: var(--t) with --t: width 1s ease-in 200ms renders { transition: ["width", 1000, "ease-in", 200] }, where the written value renders transitionProperty, transitionDuration, transitionDelay and transitionTimingFunction.
  • transition-property: var(--p) names the CSS properties as written, ["width", "background-image", "border-inline-start-color"], and no style key is spelled that way.

The written path names a transition by the property's camelCase rather than by the key the property is written to, so transition-property: background-image names backgroundImage where the style is experimental_backgroundImage, and border-inline-start-color names borderInlineStartColor where it is borderStartColor. Such a transition never matches the style it was written for.

Solution

  • propertyRename moves to utilities beside toRNProperty, and transitionStyleKey names the key a transition animates, for the compiler and the runtime alike.
  • transition and transition-property resolve at runtime when written with a var(). The transition resolver reads each comma group by CSS Transitions 1 §2.5 — any order, the first time the duration and the second the delay — into the longhands the compiler builds for a written value, and gives up on a group that is not a transition. transitionProperty maps a variable's names through transitionStyleKey.

A list whose every group is one token reaches the runtime without its commas, so width opacity reads as width, opacity, the only reading a valid transition allows; keeping the separator is a change of its own.

Tests

  • src/__tests__/native/transition-variables.test.tsx renders a written transition and the same value through a variable, for seven values: one transition, a list, properties alone, cubic-bezier(), a renamed property, all and a time alone. It also covers the keys a written and a variable transition-property name, and two invalid variable values. All 11 fail on main.
  • src/__tests__/utilities/property-names.test.ts holds every renamed property's transition to the key it is written to.

Verification

On Ubuntu with the workflow's steps - build, lint, typecheck, yarn test, node --test node/__tests__/*.mjs, both library builds, the web export, the unstaged-changes checks and commitlint - everything passes.

This PR's cases, run on main and here: #497 (comment)

Merge order

Stacked on #491, which gives toRNProperty the utilities home this extends, so #491 lands first.

…roperty one home

src/compiler/selectors.ts's getSelectors is imported by nothing; the
compiler builds selectors in selector-builder.ts. The module stayed
alive only through its toRNProperty, which atRules.ts and
declarations.ts imported while selector-builder.ts and stylesheet.ts
used a second copy. toRNProperty moves to utilities/property-names.ts
and every caller imports it from there.
`transition: var(--t)` reached React Native as a raw `transition` array
and `transition-property: var(--p)` as the variable's names, because the
transition grammar and the property names lived in the compiler. The
written path also named a transition by the property's camelCase rather
than by the key the property is written to, so `background-image` named
`backgroundImage` where its style is `experimental_backgroundImage`.

`propertyRename` moves to `utilities` beside `toRNProperty`, with
`transitionStyleKey` naming the key a transition animates for both
routes. A runtime `transition` resolver reads each comma group by CSS
Transitions 1 §2.5 — any order, the first time the duration and the
second the delay — into the longhands the compiler builds for a written
value, and `transitionProperty` maps a variable's names the same way.
@YevheniiKotyrlo

Copy link
Copy Markdown
Contributor Author

This PR's cases — main against this PR

src/__tests__/native/transition-variables.test.tsx from this PR, run on main (eda2b286) and here, merged into main: all 11 cases fail on main and none here.

  • a transition held in a variable expands like the written one: width 1s ease-in 200ms, width 1s, opacity 2s linear, width, opacity, width 1s cubic-bezier(0.25, 0.5, 0.75, 1), background-image 1s, all 300ms ease-out 50ms, 1s
  • a transition names the style key each property is written to
  • a transition-property held in a variable names the keys the written one names
  • a transition held in a variable with three times, or with two easing functions, is invalid and writes no transition

Run through the repo's jest on Windows with Node 26.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant